'''
UNIT INFO
Tree-frame-module

- Basic format
    -New node-objects are created and form the new mounting-point
    -these are really objects and not integers or so, although internally they
    may use some integer-id
    -Code
        self.root = self.tree.AddRoot("The father")
        child = self.tree.AppendItem(self.root, "i am a child")
        grandchild = self.tree.AppendItem(child, "i am a grandchild")
- add data to some node-object:
    -data can be a list
    -code
        self.tree.SetPyData(child, [a, b, c])
- testing in-modularly will use preset database from db_species



ADAP HIS
- hiding items
    -debugging or apply stored queries
- syncing record in modpanel
    - create a list-object for itemdata,
        with both relid, and queryfield vrs_1.1
            -see sampleLoad for sample
-drag n drop to re-link items
    -researching events
    -make db-update
    -testing
        -error because wx seems to expect an image
    -research adding images to tree -  dummy-list
    -remember the format
        -put it on top
    -refresh, possibs
        -delete and requery stuff
    - update modDate
-colorcoding tree-items
    -start with field colormap based on Change-field
        -adapt query
            -choose tool which can alter view
    -research item-coloring
    -test with new field colorcode
        -change default db
        -adapt code for test
    -betterings
        -forthplant hidden items
        -use more friendly colors
        -adapt queries for co-taking msdate (not null)
            -pseudocode (x=colorcode):
                if change=h then x=h
                else if msdate not not then x = dat
                else x=change
- implement additional criteria,
    - subjects
-add the ability to add extra filter-criteria to the tree

ADAP NO


ADAP FUT
-improve images
-colorcoding tree-items
    -adapt for tree-left and tree-seek
    (blue because no colorcode has been defined, takes values from next column)
    -add dummy-field colorcode (= null)
    -adapt query for fe (becomes 'dat' because of date-override)
    -generalize the code
        -try a colormap-list or -dict
-drag-and-drop-test
    - test and make sure that drop-target is not in own branche
        (parent is dropped on child > orphanizing - circular)

'''

##import jocallback
import wx
import pardb



class treePanel(wx.Panel):
    def __init__(self, parent, ID, pos = wx.DefaultPosition,
            size = wx.DefaultSize):
        wx.Panel.__init__(self, parent,ID, pos, size)

        self.treec = wx.TreeCtrl(self,-1,
            style=wx.TR_ROW_LINES|wx.TR_HAS_BUTTONS)
        # add imagelist here (a dummy-list for now to enable drag n drop)
        self.treec.SetImageList(wx.ImageList(1,1))

        self.treec.SetIndent(40)
        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onAnyEvent, self.treec)
        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.onAnyEvent, self.treec)
        self.treec.Bind(wx.EVT_LEFT_DCLICK, self.onAnyEvent)
        self.treec.Bind(wx.EVT_TREE_BEGIN_DRAG, self.onAnyEvent)
        self.treec.Bind(wx.EVT_TREE_END_DRAG, self.onAnyEvent)

        # sizing
        self.hbox = wx.BoxSizer(wx.HORIZONTAL)
        self.hbox.Add(self.treec, 1, wx.EXPAND)
        self.SetSizer(self.hbox)

        # define colors
        self.setColors()

    def setColors(self):
        colBase = wx.ColourDatabase()
        self.clPurple = colBase.Find('PURPLE')
        self.clSeaGreen = colBase.Find('SEA GREEN')
        self.clOrange = colBase.Find('ORANGE')
        self.clTurquoise = colBase.Find('TURQUOISE')
        self.clBrown = colBase.Find('BROWN')
        self.clSlateBlue = colBase.Find('SLATE BLUE')
        self.clMaroon = colBase.Find('MAROON')
        self.clGrey = colBase.Find('GREY')  # in stead of wx.LIGHT_GREY


    def onAnyEvent(self, evt):
        '''
        # override this one on call
        '''
        if evt.GetEventType() == int(wx.EVT_TREE_SEL_CHANGED._getEvtType()):
            print 'selection changed'
            curItem = evt.GetItem()
##            curItem = self.treec.GetSelection()   # works also for this event
            pyDatali = self.treec.GetPyData(curItem)
            childst = pyDatali[0]
            idvalueit = pyDatali[1]
            print childst
            print idvalueit

        elif evt.GetEventType() == int(wx.EVT_TREE_ITEM_ACTIVATED._getEvtType()):
            print 'activated'
        elif evt.GetEventType() == int(wx.EVT_LEFT_DCLICK._getEvtType()):
            self.loadTree('FDQ_RELS_TREE_RIGHT','append', 2)
        elif evt.GetEventType() == int(wx.EVT_TREE_BEGIN_DRAG._getEvtType()):
            print 'begin drag!!!'
            wx.TreeEvent.Allow(evt)
            # sample the begin-linked ID (defines where-clause)
            curItem = evt.GetItem()
            pyDatali = self.treec.GetPyData(curItem)
            self.id_dragbegin = pyDatali[1]
            print self.id_dragbegin
            # store the begin-node-item class-wide
            self.treeNode_dragBegin = curItem

        elif evt.GetEventType() == int(wx.EVT_TREE_END_DRAG._getEvtType()):
            print 'end drag!!!'
            try:
                # sample the end-linked child (becomes the new parent or object1)
                curItem = evt.GetItem()
##                print 'curitem: ' + str(curItem)
                pyDatali = self.treec.GetPyData(curItem)
                endchildst = pyDatali[0]
                endchildidit = pyDatali[1]
                print endchildst
                if endchildidit <> self.id_dragbegin:
                    # do database-update
                    pardb.updateFromParams('', 'Relations',
                            {'strings':{'object1':endchildst}},
                            {'numbers':{'RelID':self.id_dragbegin}})
                    # remove the begin-node
                    self.treec.Delete(self.treeNode_dragBegin)
                    # repopulate the end-node
                    self.loadTree('FDQ_RELS_TREE_RIGHT','appendspecific',
                        2, "" , curItem)
                else:
                    print 'can not drop on self'
            except wx._core.PyAssertionError:
                print 'Invalid drop-target'
            except:
                print 'Unanticipated error'

    def loadTree(self, tablest, loadtypest, maxdepthit=2,
            rootst='', treeNodeItem = None, extracritdi={}):
        '''
        UNIT INFO
        Table must be n-fielded with the  fields:
        -parent
        -child
        -showchild
        -id
        -colorcode
        x Maxdepth is the maximal number of levels loaded in the tree
        x pyDatali has format: [showchild, id]
        '''

        fieldlistli = pardb.getFieldList('', tablest)
        self.parentfieldst = fieldlistli[0]
        self.childfieldst = fieldlistli[1]
        self.showchildfieldst = fieldlistli[2]
        self.idfieldst = fieldlistli[3]
        self.colorcodest = fieldlistli[4]

        self.maxdepthit = maxdepthit
        if loadtypest == 'baseroot':
            self.treec.DeleteAllItems()
            root = self.treec.AddRoot(rootst)
            pyDatali = [rootst, 0]
            self.treec.SetPyData(root, pyDatali)
            self.loadTreeLevel(tablest, rootst, root, 1, loadtypest,  
                               extracritdi=extracritdi)

        elif loadtypest == 'append':
            treeItem = self.treec.GetSelection()
            self.treec.DeleteChildren(treeItem)
            parentvaluest = self.treec.GetPyData(treeItem)[0]
            self.loadTreeLevel(tablest, parentvaluest, treeItem, 1, loadtypest, 
                               extracritdi = extracritdi)
            self.treec.ExpandAllChildren(treeItem)

        elif loadtypest == 'appendspecific':
            treeItem = treeNodeItem
            print "treeItem = " + str(treeItem)
            self.treec.DeleteChildren(treeItem)
            parentvaluest = self.treec.GetPyData(treeItem)[0]
            self.loadTreeLevel(tablest, parentvaluest, treeItem, 1, loadtypest, 
                               extracritdi=extracritdi)
            self.treec.ExpandAllChildren(treeItem)

        elif loadtypest == 'expandpathway':
            treeItem = self.treec.GetRootItem()

            parentvaluest = self.treec.GetPyData(treeItem)[0]
            self.loadTreeLevel(tablest, parentvaluest, treeItem, 1, loadtypest)
            self.treec.ExpandAllChildren(treeItem)

        self.treec.ExpandAll()

    def loadTreeLevel(self, tablest, parentvaluest, parent, curdepthit,
                        loadtypest, propagatecolorbo=False,  extracritdi={}):
        '''
        ADAP HIS
        for expandpathway:
        -check if a certain node exists allready, else add it to the tree
            -write a function findTreeItem
        -efficiency-bettering
            v-improve data-query -see there
            v-python uses call by object-reference, so unstacking calls does
            not help much because they refer to the same object.
        - use extra criteria for subject
            - extracritdi

        ADAP NO

        ADAP FU
        '''
##        jocallback.setStatusBar(parentvaluest,0, True)

        
##        childrenli2 = pardb.readFromParams('', tablest, [self.childfieldst,
##                self.showchildfieldst,self.idfieldst, self.colorcodest],
##                    {'strings':{self.parentfieldst: parentvaluest}})

##        extracritdi = {'strings':{'Subject':'b1'}}

        parentcritdi = {'strings':{self.parentfieldst: parentvaluest}}
        if extracritdi == {}:
            fullcritdi = parentcritdi
        else:
            fullcritdi = pardb.mergeCritDicts(parentcritdi, extracritdi)

        childrenli2 = pardb.readFromParams('', tablest, [self.childfieldst,
                self.showchildfieldst,self.idfieldst, self.colorcodest],
                    fullcritdi)


        for row in childrenli2:
            childvaluest = row[0]
            showchildvaluest = row[1]
            idvalueit = row[2]
            colcodest = row[3]
            # --------------
            resumenormalbo = False
            if loadtypest == 'expandpathway':
                # test if child is already present here
                item = self.findTreeItem(parent, showchildvaluest)
                if not str(type(item)) == "<type 'NoneType'>": # item found!
                    self.treec.SelectItem(item)
                    # recurse without appending
                    if curdepthit < self.maxdepthit:
                        self.loadTreeLevel(tablest, childvaluest, item,
                            curdepthit + 1, loadtypest)
                else:
                    resumenormalbo = True
            # --------------
            if loadtypest <> 'expandpathway' or resumenormalbo:
                child = self.treec.AppendItem(parent, str(showchildvaluest))
                pyDatali = [childvaluest, idvalueit]
                self.treec.SetPyData(child, pyDatali)

                # apply colors
                if propagatecolorbo:
                    self.treec.SetItemTextColour(child, self.clGrey)
                else:
                    if not(str(colcodest) == 'None' or colcodest == ''): # to subscript
                        if colcodest == 'h':
                            self.treec.SetItemTextColour(child, self.clGrey)
                        elif colcodest == 'f':
                            self.treec.SetItemTextColour(child, self.clPurple)
                        elif colcodest[0:2] == 'xp':
                            self.treec.SetItemTextColour(child, self.clSeaGreen)
    ##                    elif colcodest == 'fe':     # not yet implemented in query
    ##                        self.treec.SetItemTextColour(child, wx.GREEN)
                        elif colcodest == 'dat':
                            self.treec.SetItemTextColour(child, self.clOrange)
                        else:
                            self.treec.SetItemTextColour(child, wx.BLUE)

                # recursive
                if curdepthit < self.maxdepthit:
                    if colcodest == 'h':
                        self.loadTreeLevel(tablest, childvaluest, child,
                            curdepthit + 1, loadtypest, True, extracritdi)
                    else:
                        self.loadTreeLevel(tablest, childvaluest, child,
                            curdepthit + 1, loadtypest, propagatecolorbo,  
                            extracritdi)


    def findTreeItem(self, parent, itemtekst):
        '''
        UNIT INFO:
        -find tree-item on one level only;
        -if found return it, otherwise the return-type will be of 'nonetype'
        '''
        tr = self.treec
        (child, cookie) = tr.GetFirstChild(parent)
        if child.IsOk():
            tekst= tr.GetItemText(child)
            if tekst <> itemtekst:
                while child.IsOk():
                    (child, cookie) = tr.GetNextChild(parent, cookie)
                    if child.IsOk():
                        tekst= tr.GetItemText(child)
                        print tekst
                        if tekst == itemtekst:
                            break

        if child.IsOk(): return child


    def sampleLoad(self):
        #==============
        # customize this code for testing

        self.root = self.treec.AddRoot("The Root Item")
        self.treec.SetPyData(self.root, None)
##        self.treec.SetItemImage(self.root, fldridx, wx.TreeItemIcon_Normal)
##        self.treec.SetItemImage(self.root, fldropenidx, wx.TreeItemIcon_Expanded)

        pyData = [0,1,2]
        for x in range(15):
            child = self.treec.AppendItem(self.root, "Item %d" % x)
            self.treec.SetPyData(child, pyData)
##            self.treec.SetItemImage(child, fldridx, wx.TreeItemIcon_Normal)
##            self.treec.SetItemImage(child, fldropenidx, wx.TreeItemIcon_Expanded)

            for y in range(5):
                last = self.treec.AppendItem(child, "item %d-%s" % (x, chr(ord("a")+y)))
                self.treec.SetPyData(last, pyData)
##                self.treec.SetItemImage(last, fldridx, wx.TreeItemIcon_Normal)
##                self.treec.SetItemImage(last, fldropenidx, wx.TreeItemIcon_Expanded)

                for z in range(5):
                    item = self.treec.AppendItem(last,  "item %d-%s-%d" % (x, chr(ord("a")+y), z))
                    self.treec.SetPyData(item, pyData)
##                    self.treec.SetItemImage(item, fileidx, wx.TreeItemIcon_Normal)
##                    self.treec.SetItemImage(item, smileidx, wx.TreeItemIcon_Selected)

        self.treec.ExpandAll()

##        self.treec.Expand(self.root)
##        self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, self.treec)
##        self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, self.treec)
##        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.treec)
##        self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnBeginEdit, self.treec)
##        self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndEdit, self.treec)
##        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivate, self.treec)
##
##        self.treec.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
##        self.treec.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
##        self.treec.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)

        #==============


class someFrame (wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(500, 400))


        extracritdi = {'strings':{'Subject':'b1'}}
        treep = treePanel (self, -1)
##        treep.loadTree('FDQ_RELS_TREE_RIGHT','baseroot',3,'base root')
        treep.loadTree('FDQ_RELS_TREE_RIGHT','baseroot',4,'testchen', 
                       extracritdi=extracritdi)

##        treep.sampleLoad()

##        root = treep.treec.GetRootItem()
##        item = treep.findTreeItem(root, 'treeview maken     (1x1) ')
##        print type(item)
##        if not str(type(item)) == "<type 'NoneType'>":
##            print 'xxxxxxxxxxx'
##            print treep.treec.GetItemText(item)



class myApp(wx.App):
    def OnInit(self):
        frm = someFrame(None, -1, 'TreeCtrl')
        frm.Show(True)
        self.SetTopWindow(frm)
        return True

if __name__ == '__main__':
    app = myApp(0)
    app.MainLoop()
